package main

import (
	"fmt"
	"log"
	"os"
)

//log包中有3个系列的日志打印函数，分别print系列、panic系列、fatal系列。
/*
print  单纯打印日志
panic  打印日志，抛出panic异常,遇到defer，会执行defer函数
fatal  打印日志，强制结束程序(os.Exit(1))，defer函数不会执行

log.fatal(err) 报错之后会立即终止整个程序(不执行defer)
panic(err)  报错之后会终止当前报错的协程，然后返回到调用此函数的入口处继续执行
*/

func main() {
	defer fmt.Println("发生了 panic错误！")
	log.Print("my log")
	log.Printf("my log %d", 100)
	name := "tom"
	age := 20
	log.Println(name, " ", age)
	log.Panic("致命错误！")
	// log.Fatal("致命错误！")
	log.Println("end...")
}

/*
log配置,标准log配置
默认情况下log只会打印出时间，但是实际情况下我们还需要获取文件名，行号等信息，log包提供给我们定制的接口。
log包提供两个标准log配置的相关方法：
func Flags() int // 返回标准log输出配置
func SetFlags(flag int) // 设置标准log输出配置
*/
const (
	// 控制输出日志信息的细节，不能控制输出的顺序和格式。
	// 输出的日志在每一项后会有一个冒号分隔，例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
	Ldate         = 1 << iota     // 日期，2009/01/23
	Ltime                         // 时间，01:23:23
	Lmicroseconds                 // 微秒级别的时间，01:23:23.123123（用于增强Ltime位）
	Llongfile                     // 文件全路径名+行号，/a/b/c/d.go:23
	Lshortfile                    // 文件名+行号，d.go:23（会覆盖掉Llongfile）
	LUTC                          // 使用UTC时间
	LstdFlags     = Ldate | Ltime // 标准logger的初始值
)

func maioon() {
	i := log.Flags()
	fmt.Printf("i: %v\n", i)
	log.SetFlags(log.Ldate | log.Ltime | log.Llongfile) //日志打印文件名称，时间，日志输出内容
	log.Println("my log")
}

/*
日志前缀配置
log包提供两个日志前缀配置的相关函数：
func Prefix() string // 返回日志的前缀配置
func SetPrefix(prefix string) // 设置日志前缀
*/
func maipon() {
	s := log.Prefix()
	fmt.Printf("s: %v\n", s)
	log.SetPrefix("MyLog: ") // 设置日志前缀
	s = log.Prefix()
	fmt.Printf("s: %v\n", s) // 返回日志的前缀配置
	log.Print("my log...")
}

/*日志输出位置配置
前面介绍的都是将日志输出到控制台上，golang的log包还支持将日志输出到文件中，
log包提供了func SetOutput(w io.Writer)函数，将日志输出到文件中。
日志输出位置配置*/

func maioln() {
	logFile, err := os.OpenFile("a.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Panic("打开日志文件异常")
	}
	log.SetOutput(logFile) //输出到日志文件
	log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
	log.Println("这是一条很普通的日志。")
	log.SetPrefix("[小王子]")
	log.Println("这是一条很普通的日志。")
}

/*自定义logger
log包为我们提供了内置含糊，让我们能自定义logger。从效果上来看，就是将标题3中的标准日志配置、日志前缀配置、日志输出位置配置整合到一个函数中，
使日志配置不在那么繁琐。
log包中提供了func New(out io.Writer, prefix string, flag int) *Logger函数来实现自定义logger。*/

var logger *log.Logger

func init() {
	logFile, err := os.OpenFile("a.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Panic("打开日志文件异常")
	}
	//New创建一个Logger对象,输出到日志文件，日志头是success
	logger = log.New(logFile, "success", log.Ldate|log.Ltime|log.Lshortfile)
}

func mauiin() {
	logger.Println("自定义logger")
}

//结果：日志输出到当前目录下的a.log文件中

// 如果你要使用标准的logger，我们通常会把上面的配置操作写到init函数中
func init() {
	logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println("open log file failed, err:", err)
		return
	}
	log.SetOutput(logFile)
	log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
}
